<?php
//----------------------系统快捷函数--------------------
/** 系统工具函数
 * @param string $class_name
 * @return 获取容器的类对象，如果实例化了返回对象，未实例化返回true
 * */
function getClass($class_name)
{
    return app::get_class($class_name);
}

/** 系统工具函数
 * @param string $file 配置所属文件名
 * @param string $key 配置下标
 * @param string $default 默认值
 * @return 获取配置,只支持获取二级下标
 * */
function getConfig($file, $key = '', $default = '')
{
    return app::get_config($file, $key, $default);
}

/** 系统工具函数
 * @param string $file 配置所属文件名
 * @param string $key 配置下标
 * @param string $default 默认值
 * @return 初始化数据库链接
 * */
function initDb()
{
    try {
        /*有问题的TP ORM 2.0.37的配置写法，文档全瞎写的，一个吊不起来*/
//        $db = new \think\DbManager();
//        $db->setConfig(getConfig('database'));
//        app::set_class('db', $db);
//        return $db;

        \think\Db::setConfig(getConfig('database', 'db'));//TP5.1
    } catch (\Exception $exception) {
        msg_no($exception->getMessage());
    }
}

/**
 * @param string $tabel 模板地址，从应用名开始
 * @return model实例化模型
 * */
function model($tabel)
{
    $m = '\app\model\\' . $tabel;
    return new $m;
}

/**
 * @param string $tabel
 * @return \think\Db::name
 * */
function dbm($tabel)
{
    return \think\Db::name($tabel);
}

/** 系统工具函数cache_path
 * https://www.kancloud.cn/manual/think-template/1286403
 * @param string $template 模板地址，从应用名开始
 * @param string $var 要渲染的变量
 * @return 初始化模板引擎
 * */
function admin_view($template = '', $var = [])
{
    //如果是ajax，就返回json数据，此ajax必须是参数名为 is_ajax的有值，并非请求类型是ajax异步请求
    if (!empty($_SERVER['is_ajax'])) {
        return api('is ok', $var, 201);
    }

    try {
        $view = app::get_class('view');
        //容器没有模板对象，就初始化模板对象并注入容器
        if ($view == false) {
            //模板引擎配置,前三个是公共配置，后三个是后台模板配置选项
            $config = [
                'view_suffix' => app::get_config('sys', 'view_suffix'),
                'auto_rule' => app::get_config('sys', 'auto_rule'),
                'tpl_cache' => app::get_config('sys', 'tpl_cache'),
                'taglib_pre_load' => app::get_config('sys', 'taglib_pre_load'),
                'view_path' => app::get_config('sys', 'admin_view_path'),
                'view_dir_name' => app::get_config('sys', 'admin_view_dir_name'),
                'cache_path' => app::get_config('sys', 'admin_cache_path'),
            ];
            $view = new \think\Template($config);
            app::set_class('view', $view);//将对象放入容器
        }
        if ($template == '') {
            $template = 'modules' . LINE . ROUTE_M . LINE . 'view' . LINE . ROUTE_C . LINE . ROUTE_A;
        } else {
            $tmp = explode('@', $template);
            if (count($tmp) == 2) {
                //如果使用@就是 模块@模板名称（view不用写，自动拼接，可以是view下多级目录），可以指定其他模块下的，同方法名模板名
                $tmp[0] = $tmp[0] ? $tmp[0] : ROUTE_M;
                $tmp[1] = $tmp[1] ? $tmp[1] : ROUTE_C . LINE . ROUTE_A;
                $template = 'modules' . LINE . $tmp[0] . LINE . 'view' . LINE . $tmp[1];
            } else {
//                dd($tmp);
                //没有写@认定为当前所属模块，值为模板名称（可以带view下目录名，）
                $template = 'modules' . LINE . ROUTE_M . LINE . 'view' . LINE . $tmp[0];
            }
        }
        $view->fetch($template, $var);
        return $view;
    } catch (\Exception $exception) {
        msg_no($exception->getMessage());
    }
}

/**
 * @param $msg  提示信息
 * @param $data 数据
 * @param $code 接口判断码
 * @param $err_code 错误类型码
 * @return api返回json数据
 */
function api($msg, $data = array(), $code = 201, $err_code = null)
{
    if (!$msg) {
        return 'msg not';
    }
    $api_data['msg'] = $msg;    //提示
    $api_data['data'] = $data;  //数据
    $api_data['code'] = $code;  //接口判断码
    if ($err_code) $api_data['err_code'] = $err_code;//错误类型码
    return to_json($api_data);
}

//生成图片可以，转的还没调试完
function base64EncodeImage($houzhui, $dizhi, $str)
{
    switch ($houzhui) {
        case 'image/png':
            $im = imagecreatefrompng($dizhi);
            break;
        case 'image/gif':
            $im = imagecreatefromgif($dizhi);
            break;
        case 'image/jpeg':
            $im = imagecreatefromjpeg($dizhi);
            break;
        case 'image/jpg':
            $im = imagecreatefromjpeg($dizhi);
            break;
        default:
            exit("上传文件格式不正确");
            break;
    }
//    header("Content-type:image/webp");
    imagewebp($im, './' . $str . '.webp', 1);
    imagedestroy($im);
//    $name = 'img/' . $str . '.webp';
//    return base64_encode(file_get_contents($name));//先将文件写入字符串，在进行base64编码
}

/**
 * @param $url  接口地址
 * @param $http_method 请求方式
 * @param $data 请求数据
 * @param $header 请求头(一维非关联数组)
 * @param $cookie 请cookie
 * @return 发送https的post请求
 */
function http_curl($url, $http_method = 'GET', $data = '', $header = array(), $cookie = '')
{
    $headers = array(
        'Accept: application/json',
    );
    $headers = array_merge($headers, $header);
    if ($cookie) {
        $headers[] = "Cookie: $cookie";
    }
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
    curl_setopt($ch, CURLOPT_HEADER, FALSE);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);//设置是将结果保存还是输出到屏幕
    //post提交方式
    if ($http_method == 'POST' && $data) {
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    }

    $res = curl_exec($ch);
    //返回结果
    if ($res) {
        curl_close($ch);
        return $res;
    } else {
        $error = curl_errno($ch);
        curl_close($ch);
        return $error;
    }
}

function downImg($url, $path = "./download/images/")
{
    // 因为不知道最后接受到的文件是什么格式，先建立一个临时文件，用于保存
    $tmpFile = tempnam(sys_get_temp_dir(), 'image');

    # 文件下载 BEGIN #

    // 打开临时文件，用于写入（w),b二进制文件
    $resource = fopen($tmpFile, 'wb');

    // 初始化curl
    $curl = curl_init($url);
    // 设置输出文件为刚打开的
    curl_setopt($curl, CURLOPT_FILE, $resource);
    // 不需要头文件
    curl_setopt($curl, CURLOPT_HEADER, 0);
    // 执行
    curl_exec($curl);
    // 关闭curl
    curl_close($curl);

    // 关闭文件
    fclose($resource);

    # 文件下载 END #

    // 获取文件类型
    if (function_exists('exif_imagetype')) {
        // 读取一个图像的第一个字节并检查其签名(这里需要打开mbstring及php_exif)
        $fileType = exif_imagetype($tmpFile);
    } else {
        // 获取文件大小，里面第二个参数是文件类型 （这里后缀可以直接通过getimagesize($url)来获取，但是很慢）
        $fileInfo = getimagesize($tmpFile);
        $fileType = $fileInfo[2];
    }


    // 根据文件类型获取后缀名
    $extension = image_type_to_extension($fileType);

    // 计算指定文件的 MD5 散列值，作为保存的文件名，重复下载同一个文件不会产生重复保存，相同的文件散列值相同
    $md5FileName = md5_file($tmpFile);

    // 最终保存的文件
    $returnFile = $path . $md5FileName . $extension;

    // 检查传过来的路径是否存在，不存在就创建
    if (!is_dir($path)) {
        mkdir($path, 0777, true);
    }

    // 复制临时文件到最终保存的文件中
    copy($tmpFile, $returnFile);

    // 释放临时文件
    @unlink($tmpFile);

    // 返回保存的文件路径
    return $returnFile;
}

/**
 * 批量数据验证
 * @param array $data 数据
 * @return 接受参数并验证
 */
function I(array $data)
{
    if (is_array($data)) {
        if (!is_array($data[0])) return msg_no('I方法，必须是二位数组，每个第二维数组都是一个接受的参数');
        return app::get_class('validata')->check($data);
    }
    return false;
}

// 获取路径中的文件名
function file_name($path)
{
    return substr($path, strrpos($path, '/') + 1);
}

/**
 * @return 对字符串进行编码 URL 字符串
 * */
function url_encode($s)
{
    $s = urlencode($s);
    $s = str_replace('_', '_5f', $s);
    $s = str_replace('-', '_2d', $s);
    $s = str_replace('.', '_2e', $s);
    $s = str_replace('+', '_2b', $s);
    $s = str_replace('=', '_3d', $s);
    $s = str_replace('%', '_', $s);
    return $s;
}

/**
 * @return 解码 xn\_urlencode() 编码的字符串
 * */
function url_decode($s)
{
    $s = str_replace('_', '%', $s);
    $s = urldecode($s);
    return $s;
}

/**
 * @return 获取字符串某个字符之后的内容
 * */
function get_this_after_str($data, $sign)
{
    $res = substr($data, strripos($data, "{$sign}") + 1);
    return $res;
}

/**
 * @return 获取字符串某个字符之前的内容
 * */
function get_this_front_str($data, $sign)
{
    $res = substr($data, 0, strrpos($data, "{$sign}"));
    return $res;
}

/**
 * 方法借鉴tp3.2
 * 获取输入参数 支持过滤和默认值
 * 使用方法:
 * <code>
 * input('id',0); 获取id参数 自动判断get或者post
 * input('post.name','','htmlspecialchars'); 获取$_POST['name']
 * input('get.'); 获取$_GET
 * </code>
 * @param string $name 变量的名称 支持指定类型
 * @param mixed $default 不存在的时候默认值
 * @param mixed $filter 参数过滤方法
 * @param mixed $datas 要获取的额外数据源
 * @return 参数接受函数
 */
function input($name, $default = '', $filter = null, $datas = null)
{
    static $_PUT = null;
    if (strpos($name, '/')) { // 指定修饰符
        list($name, $type) = explode('/', $name, 2);
    } else { // 输入变量是否自动强制转换为字符串 如果开启则数组变量需要手动传入变量修饰符获取变量
        $type = 's';
    }
    if (strpos($name, '.')) { // 指定参数来源
        list($method, $name) = explode('.', $name, 2);
    } else { // 默认为自动判断
        $method = 'request';
    }
    switch (strtolower($method)) {
        case 'get'     :
            $input =& $_GET;
            break;
        case 'post'    :
            $input =& $_POST;
            break;
        case 'request' :
            $input =& $_REQUEST;
            break;
        case 'session' :
            $input =& $_SESSION;
            break;
        case 'cookie'  :
            $input =& $_COOKIE;
            break;
        case 'server'  :
            $input =& $_SERVER;
            break;
        case 'globals' :
            $input =& $GLOBALS;
            break;
        case 'data'    :
            $input =& $datas;
            break;
        default:
            return null;
    }
    if ('' == $name) { // 获取全部变量
        $data = $input;
        $filters = isset($filter) ? $filter : app::get_config('sys', 'define_filter');// 参数用 $filter 指定的方法过滤
        if ($filters) {
            if (is_string($filters)) {
                $filters = explode(',', $filters);
            }
            foreach ($filters as $filter) {
                $data = array_map_recursive($filter, $data); // 参数用 $filter 指定的方法过滤
            }
        }
    } elseif (isset($input[$name])) { // 取值操作
        $data = $input[$name];
        $filters = isset($filter) ? $filter : app::get_config('sys', 'define_filter');// 参数用 $filter 指定的方法过滤
        if ($filters) {
            if (is_string($filters)) {
                if (0 === strpos($filters, '/')) {
                    if (1 !== preg_match($filters, (string)$data)) {
                        // 支持正则验证
                        return isset($default) ? $default : null;
                    }
                } else {
                    $filters = explode(',', $filters);
                }
            } elseif (is_int($filters)) {
                $filters = array($filters);
            }

            if (is_array($filters)) {
                foreach ($filters as $filter) {
                    if (function_exists($filter)) {
                        $data = is_array($data) ? array_map_recursive($filter, $data) : $filter($data); // 参数过滤
                    } else {
                        $data = filter_var($data, is_int($filter) ? $filter : filter_id($filter));
                        if (false === $data) {
                            return isset($default) ? $default : null;
                        }
                    }
                }
            }
        }
        if (!empty($type)) {
            switch (strtolower($type)) {
                case 'a':    // 数组
                    $data = (array)$data;
                    break;
                case 'd':    // 数字
                    $data = (int)$data;
                    break;
                case 'f':    // 浮点
                    $data = (float)$data;
                    break;
                case 'b':    // 布尔
                    $data = (boolean)$data;
                    break;
                case 's':   // 字符串
                default:
                    $data = (string)$data;
            }
        }
    } else { // 变量默认值
        $data = isset($default) ? $default : null;
    }
    is_array($data) && array_walk_recursive($data, 'anquan_wek_filter');
    return $data;
}
//安全过滤
function array_map_recursive($filter, $data)
{
    $result = array();
    foreach ($data as $key => $val) {
        $result[$key] = is_array($val)
            ? array_map_recursive($filter, $val)
            : call_user_func($filter, $val);
    }

    return $result;
}

//安全过滤
function anquan_wek_filter(&$value)
{
    // TODO 其他安全过滤

    // 过滤查询特殊字符：加一个空格
    if (preg_match('/^(EXP|NEQ|GT|EGT|LT|ELT|OR|XOR|LIKE|NOTLIKE|NOT BETWEEN|NOTBETWEEN|BETWEEN|NOTIN|NOT IN|IN)$/i', $value)) {
        $value .= ' ';
    }
}

/** 系统工具函数
 * @param string $data 打印的数据
 * @param string $detailed 是否var_dump打印详细信息
 * @return 不中断后续代码打印数据
 * */
function dv($data = '', $detailed = 0)
{
    if (is_bool($data)) {
        var_dump($data);
    } else if (is_null($data)) {
        var_dump(null);
    } else {
        if (is_string($data)) {
            echo($data);
        } else {
            if ($detailed) {
                echo '<pre>';
                var_dump($data);
                echo '</pre>';
            } else {
                echo '<pre>';
                print_r($data);
                echo '</pre>';
            }
        }
    }
}

/** 系统工具函数
 * @param string $data 打印的数据
 * @param string $detailed 是否var_dump打印详细信息
 * @return 中断后续代码打印数据
 * */
function dd($data = '', $detailed = 0)
{
    if (is_bool($data)) {
        var_dump($data);
    } else if (is_null($data)) {
        var_dump(null);
    } else {
        if (is_string($data)) {
            echo $data;
        } else {
            if ($detailed) {
                echo '<pre>';
                var_dump($data);
                echo '</pre>';
            } else {
                echo '<pre>';
                print_r($data);
                echo '</pre>';
            }
        }
    }
    exit();
}

function redirect($url)
{
    header("Location: {$url}");
    exit();
}

/** 系统工具函数
 * @param string $name 请求头
 * @return 获取请求头
 * */
function getHeaders($name = '')
{
    static $header = [];
    if ($header != []) {
        if ($name == '') {
            return $header;
        }
        if (isset($header[$name])) {
            return $header[$name];
        }
    }
    if (function_exists('apache_request_headers') && $result = apache_request_headers()) {
        $header = $result;
    } else {
        $server = $_SERVER;
        foreach ($server as $key => $val) {
            if (0 === strpos($key, 'HTTP_')) {
                $key = str_replace('_', '-', strtolower(substr($key, 5)));
                $header[$key] = $val;
            }
        }
        if (isset($server['CONTENT_TYPE'])) {
            $header['content-type'] = $server['CONTENT_TYPE'];
        }
        if (isset($server['CONTENT_LENGTH'])) {
            $header['content-length'] = $server['CONTENT_LENGTH'];
        }
    }
    $header = array_change_key_case($header);//CASE_LOWER - 默认值。将数组的键转换为小写字母。CASE_UPPER - 将数组的键转换为大写字母。
    if ($name == '') {
        return $header;
    }
    if (isset($header[$name])) {
        return $header[$name];
    }
    return false;
}


/**
 * 获取请求ip
 * @param integer $type 返回类型 0 返回IP地址 1 返回IPV4地址数字
 * @param boolean $adv 是否进行高级模式获取（有可能被伪装）
 * @return ip地址
 */
function ip($type = 0, $adv = false)
{
    $type = $type ? 1 : 0;
    static $ip = NULL;
    if ($ip !== NULL) return $ip[$type];
    if ($adv) {
        if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            $arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
            $pos = array_search('unknown', $arr);
            if (false !== $pos) unset($arr[$pos]);
            $ip = trim($arr[0]);
        } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
            $ip = $_SERVER['HTTP_CLIENT_IP'];
        } elseif (isset($_SERVER['REMOTE_ADDR'])) {
            $ip = $_SERVER['REMOTE_ADDR'];
        }
    } elseif (isset($_SERVER['REMOTE_ADDR'])) {
        $ip = $_SERVER['REMOTE_ADDR'];
    }
    // IP地址合法验证
    $long = sprintf("%u", ip2long($ip));
    $ip = $long ? array($ip, $long) : array('0.0.0.0', 0);
    return $ip[$type];
}

/**
 * 程序执行消耗时间和内存
 * @return    int    单位ms
 */
function sys_over()
{
    return array(
        'time' => round(microtime(true) - SYS_START_TIME, 4),//秒
        'stock' => round((memory_get_usage() - SYS_START_MEMORY) / 1024, 4),//kb
    );
}

/**
 * 程序执行消耗时间
 * @return    int    程序执行消耗时间单位ms
 */
function sys_over_time()
{
    $wek = sys_over();
    return $wek['time'];
}

/**
 * 程序执行消耗内存
 * @return    int    程序执行消耗内存单位kb
 */
function sys_over_stock()
{
    $wek = sys_over();
    return $wek['stock'];
}

//初始化设置
function _wek_init_session($name)
{
    //session方法的第一个参数传入数组则表示进行自定义session初始化启动设置
    //session(array('name'=>'session_id','expire'=>3600));
    ini_set('session.auto_start', 0);
    if (isset($name['id'])) session_id($name['id']);
    if (isset($name['name'])) session_name($name['name']);
    if (isset($name['path'])) session_save_path($name['path']);
    if (isset($name['domain'])) ini_set('session.cookie_domain', $name['domain']);
    if (isset($name['expire'])) {
        ini_set('session.gc_maxlifetime', $name['expire']);
        ini_set('session.cookie_lifetime', $name['expire']);
    }
    if (isset($name['use_trans_sid'])) ini_set('session.use_trans_sid', $name['use_trans_sid'] ? 1 : 0);
    if (isset($name['use_cookies'])) ini_set('session.use_cookies', $name['use_cookies'] ? 1 : 0);
    if (isset($name['cache_limiter'])) session_cache_limiter($name['cache_limiter']);
    if (isset($name['cache_expire'])) session_cache_expire($name['cache_expire']);
}

/**
 * @param $name
 * @param $value
 * @return  设置 session
 */
function setSession($name = '', $value = '')
{
    $prefix = getConfig('sys', 'session_prefix');
    //防止重复启动
    if ($GLOBALS['session_start'] === false) {
        if (is_array($name)) {
            //session方法的第一个参数传入数组则表示进行自定义session初始化启动设置
            //session(array('name'=>'session_id','expire'=>3600));
            _wek_init_session($name);
        } else {
            ini_set('session.gc_maxlifetime', 2 * $GLOBALS['day']);
            ini_set('session.cookie_lifetime', 2 * $GLOBALS['day']);
        }
        // 用就启动session
        session_start();
        $GLOBALS['session_start'] = true;
    }
    if (!empty($name) && !empty($value)) {
        if (strpos($name, '.')) {//二位数组设置
            list($name1, $name2) = explode('.', $name);
            if ($prefix) {
                $_SESSION[$prefix][$name1][$name2] = $value;
            } else {
                $_SESSION[$name1][$name2] = $value;
            }
        } else {
            if ($prefix) {//单个设置
                $_SESSION[$prefix][$name] = $value;
            } else {
                $_SESSION[$name] = $value;
            }
        }
    }
    //删除session的值
    if (!empty($name) && !$value) {
        if (strpos($name, '.')) {//删除二位数组session的值
            list($name1, $name2) = explode('.', $name);
            if ($prefix) {
                unset($_SESSION[$prefix][$name1][$name2]);
            } else {
                unset($_SESSION[$name1][$name2]);
            }
        } else {//删除单个session的值
            if ($prefix) {
                unset($_SESSION[$prefix][$name]);
            } else {
                unset($_SESSION[$name]);
            }
        }
    }
    //清楚所有session
    if ($name == '' || is_null($name)) {
        if ($prefix) {
            unset($_SESSION[$prefix]);
        } else {
            $_SESSION = array();
        }
    }
    if (0 === strpos($name, '[')) { // session 管理
//            setSession('[pause]'); // 暂停session写入
//            setSession('[start]'); // 启动session
//            setSession('[destroy]'); // 销毁session
//            setSession('[regenerate]'); // 重新生成session id
        if ('[pause]' == $name) { // 暂停session
            session_write_close();
        } elseif ('[start]' == $name) { // 启动session
            session_start();
        } elseif ('[destroy]' == $name) { // 销毁session
            $_SESSION = array();
            session_unset();
            session_destroy();
        } elseif ('[regenerate]' == $name) { // 重新生成id
            session_regenerate_id();
        }
    }
}

/**
 * 读取session
 * @param $name
 * @param $value
 * @return  读取session
 */
function getSession($name = '', $value = '')
{
    $prefix = getConfig('sys', 'session_prefix');
    //防止重复启动
    if ($GLOBALS['session_start'] === false) {
        if (is_array($name)) {
            //session方法的第一个参数传入数组则表示进行自定义session初始化启动设置
            //session(array('name'=>'session_id','expire'=>3600));
            _wek_init_session($name);
        } else {
            ini_set('session.gc_maxlifetime', 2 * $GLOBALS['day']);
            ini_set('session.cookie_lifetime', 2 * $GLOBALS['day']);
        }
        // 用就启动session
        session_start();
        $GLOBALS['session_start'] = true;
    }
    //获取全部
    if ($name == '' && $value == '') {
        return $prefix ? $_SESSION[$prefix] : $_SESSION;
    } else {
        //操作单个
        if (0 === strpos($name, '?')) { // 检查session
            // 判断名称为name的session值是否已经设置 getSession('?name');
            $name = substr($name, 1);
            if (strpos($name, '.')) { // 支持数组
                list($name1, $name2) = explode('.', $name);
                return $prefix ? isset($_SESSION[$prefix][$name1][$name2]) : isset($_SESSION[$name1][$name2]);
            } else {
                return $prefix ? isset($_SESSION[$prefix][$name]) : isset($_SESSION[$name]);
            }
        }
        if ($prefix) { // 有前缀获取session,
            if (strpos($name, '.')) {//二位数组取值
                list($name1, $name2) = explode('.', $name);
                return isset($_SESSION[$prefix][$name1][$name2]) ? $_SESSION[$prefix][$name1][$name2] : null;
            } else {
                return isset($_SESSION[$prefix][$name]) ? $_SESSION[$prefix][$name] : null;
            }
        } else {
            if (strpos($name, '.')) {
                list($name1, $name2) = explode('.', $name);
                return isset($_SESSION[$name1][$name2]) ? $_SESSION[$name1][$name2] : null;
            } else {
                return isset($_SESSION[$name]) ? $_SESSION[$name] : null;
            }
        }
    }
}

/**
 * Cookie 设置、获取、删除
 * @param string $name cookie名称
 * @param mixed $value cookie值
 * @param mixed $option cookie参数
 * @return mixed
 */
function cookie($name = '', $value = '', $option = null)
{
    // 默认设置
    $config = array(
        'prefix' => getConfig('sys', 'cookie_prefix'), // cookie 名称前缀
        'expire' => getConfig('sys', 'cookie_expire'), // cookie 保存时间
        'path' => getConfig('sys', 'cookie_path'), // cookie 保存路径
        'domain' => getConfig('sys', 'cookie_domain'), // cookie 有效域名
        'secure' => getConfig('sys', 'cookie_secure'), //  cookie 启用安全传输
        'httponly' => getConfig('sys', 'cookie_httponly'), // httponly设置
    );
    // 参数设置(会覆盖黙认设置)
    if (!is_null($option)) {
        if (is_numeric($option))
            $option = array('expire' => $option);
        elseif (is_string($option))
            parse_str($option, $option);
        $config = array_merge($config, array_change_key_case($option));
    }
    if (!empty($config['httponly'])) {
        ini_set("session.cookie_httponly", 1);
    }
    // 清除指定前缀的所有cookie
    if (is_null($name)) {
        if (empty($_COOKIE))
            return null;
        // 要删除的cookie前缀，不指定则删除config设置的指定前缀
        $prefix = empty($value) ? $config['prefix'] : $value;
        if (!empty($prefix)) {// 如果前缀为空字符串将不作处理直接返回
            foreach ($_COOKIE as $key => $val) {
                if (0 === stripos($key, $prefix)) {
                    setcookie($key, '', time() - 3600, $config['path'], $config['domain'], $config['secure'], $config['httponly']);
                    unset($_COOKIE[$key]);
                }
            }
        }
        return null;
    } elseif ('' === $name) {
        // 获取全部的cookie
        return $_COOKIE;
    }
    $name = $config['prefix'] . str_replace('.', '_', $name);
    if ('' === $value) {
        if (isset($_COOKIE[$name])) {
            $value = $_COOKIE[$name];
            if (0 === strpos($value, 'wekcms:')) {
                $value = substr($value, 7);
                return array_map('urldecode', json_decode(MAGIC_QUOTES_GPC ? stripslashes($value) : $value, true));
            } else {
                return $value;
            }
        } else {
            return null;
        }
    } else {
        if (is_null($value)) {
            setcookie($name, '', time() - 3600, $config['path'], $config['domain'], $config['secure'], $config['httponly']);
            unset($_COOKIE[$name]); // 删除指定cookie
        } else {
            // 设置cookie
            if (is_array($value)) {
                $value = 'think:' . json_encode(array_map('urlencode', $value));
            }
            $expire = !empty($config['expire']) ? time() + intval($config['expire']) : 0;
            setcookie($name, $value, $expire, $config['path'], $config['domain'], $config['secure'], $config['httponly']);
            $_COOKIE[$name] = $value;
        }
    }
    return null;
}

/**
 * 转json,兼容中文
 * @param string $data
 * @return 转json,兼容中文
 */
function to_json($data)
{
    if (version_compare(PHP_VERSION, '5.4.0', '<')) {
        $str = json_encode($data);
        $str = preg_replace_callback("#\\\u([0-9a-f]{4})#i", function ($matchs) {
            return iconv('UCS-2BE', 'UTF-8', pack('H4', $matchs[1]));
        }, $str);
        return $str;
    } else {
        return json_encode($data, JSON_UNESCAPED_UNICODE);
    }
}

/**
 * 去404页面
 * @return    去404页面
 */
function to404()
{
    header('HTTP/1.1 404 Not Found');
    header('Status: 404 Not Found');
    include WEKCMS_PATH . 'tmp/404.html';
    exit;
}


//错误提示信息
function msg_no($msg, $title = '发生了错误')
{
    if (DEBUG) {
        if (isset($_SERVER['ajax']) && $_SERVER['ajax'] == true) {
        } else {
            include WEKCMS_PATH . 'tmp/msg.php';
            exit;
        }
    }
    to404();
}

//正确提示信息
function msg_ok()
{

}

/**
 * @param string $str
 * @return    取字符串英文首字母
 */
function getStrInitials($str)
{
    if (empty($str)) {
        return '';
    }
    $fchar = ord($str[0]);
    if ($fchar >= ord('A') && $fchar <= ord('z')) return strtoupper($str[0]);
    $s1 = iconv('UTF-8', 'gb2312', $str);
    $s2 = iconv('gb2312', 'UTF-8', $s1);
    $s = $s2 == $str ? $s1 : $str;
    $asc = ord($s[0]) * 256 + ord($s[1]) - 65536;
    if ($asc >= -20319 && $asc <= -20284) return 'A';
    if ($asc >= -20283 && $asc <= -19776) return 'B';
    if ($asc >= -19775 && $asc <= -19219) return 'C';
    if ($asc >= -19218 && $asc <= -18711) return 'D';
    if ($asc >= -18710 && $asc <= -18527) return 'E';
    if ($asc >= -18526 && $asc <= -18240) return 'F';
    if ($asc >= -18239 && $asc <= -17923) return 'G';
    if ($asc >= -17922 && $asc <= -17418) return 'H';
    if ($asc >= -17417 && $asc <= -16475) return 'J';
    if ($asc >= -16474 && $asc <= -16213) return 'K';
    if ($asc >= -16212 && $asc <= -15641) return 'L';
    if ($asc >= -15640 && $asc <= -15166) return 'M';
    if ($asc >= -15165 && $asc <= -14923) return 'N';
    if ($asc >= -14922 && $asc <= -14915) return 'O';
    if ($asc >= -14914 && $asc <= -14631) return 'P';
    if ($asc >= -14630 && $asc <= -14150) return 'Q';
    if ($asc >= -14149 && $asc <= -14091) return 'R';
    if ($asc >= -14090 && $asc <= -13319) return 'S';
    if ($asc >= -13318 && $asc <= -12839) return 'T';
    if ($asc >= -12838 && $asc <= -12557) return 'W';
    if ($asc >= -12556 && $asc <= -11848) return 'X';
    if ($asc >= -11847 && $asc <= -11056) return 'Y';
    if ($asc >= -11055 && $asc <= -10247) return 'Z';
    return null;
}

/**
 * 返回经addslashes处理过的字符串或数组
 * @param $data 需要处理的字符串或数组
 * @return mixed
 */
function new_addslashes($data)
{
    if (!is_array($data)) return addslashes($data);
    foreach ($data as $key => $val) $data[$key] = new_addslashes($val);
    return $data;
}

/**
 * 返回经stripslashes处理过的字符串或数组
 * @param $data 需要处理的字符串或数组
 * @return mixed
 */
function new_stripslashes($data)
{
    if (!is_array($data)) return stripslashes($data);
    foreach ($data as $key => $val) $data[$key] = new_stripslashes($val);
    return $data;
}

/**
 * 返回经htmlspecialchars处理过的字符串或数组
 * @param $obj 需要处理的字符串或数组
 * @return mixed
 */
function new_html_special_chars($string)
{
    $encoding = 'utf-8';
    if (strtolower(CHARSET) == 'gbk') $encoding = 'ISO-8859-15';
    if (!is_array($string)) return htmlspecialchars($string, ENT_QUOTES, $encoding);
    foreach ($string as $key => $val) $string[$key] = new_html_special_chars($val);
    return $string;
}

function new_html_entity_decode($string)
{
    $encoding = 'utf-8';
    if (strtolower(CHARSET) == 'gbk') $encoding = 'ISO-8859-15';
    return html_entity_decode($string, ENT_QUOTES, $encoding);
}

function new_htmlentities($string)
{
    $encoding = 'utf-8';
    if (strtolower(CHARSET) == 'gbk') $encoding = 'ISO-8859-15';
    return htmlentities($string, ENT_QUOTES, $encoding);
}

/**
 * 安全过滤函数
 *
 * @param $string
 * @return string
 */
function safe_replace($string)
{
    $string = str_replace('%20', '', $string);
    $string = str_replace('%27', '', $string);
    $string = str_replace('%2527', '', $string);
    $string = str_replace('*', '', $string);
    $string = str_replace('"', '&quot;', $string);
    $string = str_replace("'", '', $string);
    $string = str_replace('"', '', $string);
    $string = str_replace(';', '', $string);
    $string = str_replace('<', '&lt;', $string);
    $string = str_replace('>', '&gt;', $string);
    $string = str_replace("{", '', $string);
    $string = str_replace('}', '', $string);
    $string = str_replace('\\', '', $string);
    return $string;
}

/**
 * xss过滤函数
 *
 * @param $string
 * @return string
 */
function remove_xss($string)
{
    $string = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S', '', $string);

    $parm1 = array('javascript', 'vbscript', 'expression', 'applet', 'meta', 'xml', 'blink', 'link', 'script', 'embed', 'object', 'iframe', 'frame', 'frameset', 'ilayer', 'layer', 'bgsound', 'title', 'base');

    $parm2 = array('onabort', 'onactivate', 'onafterprint', 'onafterupdate', 'onbeforeactivate', 'onbeforecopy', 'onbeforecut', 'onbeforedeactivate', 'onbeforeeditfocus', 'onbeforepaste', 'onbeforeprint', 'onbeforeunload', 'onbeforeupdate', 'onblur', 'onbounce', 'oncellchange', 'onchange', 'onclick', 'oncontextmenu', 'oncontrolselect', 'oncopy', 'oncut', 'ondataavailable', 'ondatasetchanged', 'ondatasetcomplete', 'ondblclick', 'ondeactivate', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave', 'ondragover', 'ondragstart', 'ondrop', 'onerror', 'onerrorupdate', 'onfilterchange', 'onfinish', 'onfocus', 'onfocusin', 'onfocusout', 'onhelp', 'onkeydown', 'onkeypress', 'onkeyup', 'onlayoutcomplete', 'onload', 'onlosecapture', 'onmousedown', 'onmouseenter', 'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onmove', 'onmoveend', 'onmovestart', 'onpaste', 'onpropertychange', 'onreadystatechange', 'onreset', 'onresize', 'onresizeend', 'onresizestart', 'onrowenter', 'onrowexit', 'onrowsdelete', 'onrowsinserted', 'onscroll', 'onselect', 'onselectionchange', 'onselectstart', 'onstart', 'onstop', 'onsubmit', 'onunload');

    $parm = array_merge($parm1, $parm2);

    for ($i = 0; $i < sizeof($parm); $i++) {
        $pattern = '/';
        for ($j = 0; $j < strlen($parm[$i]); $j++) {
            if ($j > 0) {
                $pattern .= '(';
                $pattern .= '(&#[x|X]0([9][a][b]);?)?';
                $pattern .= '|(&#0([9][10][13]);?)?';
                $pattern .= ')?';
            }
            $pattern .= $parm[$i][$j];
        }
        $pattern .= '/i';
        $string = preg_replace($pattern, ' ', $string);
    }
    return $string;
}

/**
 * 过滤ASCII码从0-28的控制字符
 * @return String
 */
function trim_unsafe_control_chars($str)
{
    $rule = '/[' . chr(1) . '-' . chr(8) . chr(11) . '-' . chr(12) . chr(14) . '-' . chr(31) . ']*/';
    return str_replace(chr(0), '', preg_replace($rule, '', $str));
}

/**
 * 格式化文本域内容
 *
 * @param $string 文本域内容
 * @return string
 */
function trim_textarea($string)
{
    $string = nl2br(str_replace(' ', '&nbsp;', $string));
    return $string;
}

/**
 * 将文本格式成适合js输出的字符串
 * @param string $string 需要处理的字符串
 * @param intval $isjs 是否执行字符串格式化，默认为执行
 * @return string 处理后的字符串
 */
function format_js($string, $isjs = 1)
{
    $string = addslashes(str_replace(array("\r", "\n", "\t"), array('', '', ''), $string));
    return $isjs ? 'document.write("' . $string . '");' : $string;
}

/**
 * 转义 javascript 代码标记
 *
 * @param $str
 * @return mixed
 */
function trim_script($str)
{
    if (is_array($str)) {
        foreach ($str as $key => $val) {
            $str[$key] = trim_script($val);
        }
    } else {
        $str = preg_replace('/\<([\/]?)script([^\>]*?)\>/si', '&lt;\\1script\\2&gt;', $str);
        $str = preg_replace('/\<([\/]?)iframe([^\>]*?)\>/si', '&lt;\\1iframe\\2&gt;', $str);
        $str = preg_replace('/\<([\/]?)frame([^\>]*?)\>/si', '&lt;\\1frame\\2&gt;', $str);
        $str = str_replace('javascript:', 'javascript：', $str);
    }
    return $str;
}

/**
 * 获取当前页面完整URL地址
 */
function get_url()
{
    $sys_protocal = isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == '443' ? 'https://' : 'http://';
    $php_self = $_SERVER['PHP_SELF'] ? safe_replace($_SERVER['PHP_SELF']) : safe_replace($_SERVER['SCRIPT_NAME']);
    $path_info = isset($_SERVER['PATH_INFO']) ? safe_replace($_SERVER['PATH_INFO']) : '';
    $relate_url = isset($_SERVER['REQUEST_URI']) ? safe_replace($_SERVER['REQUEST_URI']) : $php_self . (isset($_SERVER['QUERY_STRING']) ? '?' . safe_replace($_SERVER['QUERY_STRING']) : $path_info);
    return $sys_protocal . (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '') . $relate_url;
}

/**
 * 字符截取 支持UTF8/GBK
 * @param $string
 * @param $length
 * @param $dot
 */
function str_cut($string, $length, $dot = '...')
{
    $strlen = strlen($string);
    if ($strlen <= $length) return $string;
    $string = str_replace(array(' ', '&nbsp;', '&amp;', '&quot;', '&#039;', '&ldquo;', '&rdquo;', '&mdash;', '&lt;', '&gt;', '&middot;', '&hellip;'), array('∵', ' ', '&', '"', "'", '“', '”', '—', '<', '>', '·', '…'), $string);
    $strcut = '';
    if (strtolower(CHARSET) == 'utf-8') {
        $length = intval($length - strlen($dot) - $length / 3);
        $n = $tn = $noc = 0;
        while ($n < strlen($string)) {
            $t = ord($string[$n]);
            if ($t == 9 || $t == 10 || (32 <= $t && $t <= 126)) {
                $tn = 1;
                $n++;
                $noc++;
            } elseif (194 <= $t && $t <= 223) {
                $tn = 2;
                $n += 2;
                $noc += 2;
            } elseif (224 <= $t && $t <= 239) {
                $tn = 3;
                $n += 3;
                $noc += 2;
            } elseif (240 <= $t && $t <= 247) {
                $tn = 4;
                $n += 4;
                $noc += 2;
            } elseif (248 <= $t && $t <= 251) {
                $tn = 5;
                $n += 5;
                $noc += 2;
            } elseif ($t == 252 || $t == 253) {
                $tn = 6;
                $n += 6;
                $noc += 2;
            } else {
                $n++;
            }
            if ($noc >= $length) {
                break;
            }
        }
        if ($noc > $length) {
            $n -= $tn;
        }
        $strcut = substr($string, 0, $n);
        $strcut = str_replace(array('∵', '&', '"', "'", '“', '”', '—', '<', '>', '·', '…'), array(' ', '&amp;', '&quot;', '&#039;', '&ldquo;', '&rdquo;', '&mdash;', '&lt;', '&gt;', '&middot;', '&hellip;'), $strcut);
    } else {
        $dotlen = strlen($dot);
        $maxi = $length - $dotlen - 1;
        $current_str = '';
        $search_arr = array('&', ' ', '"', "'", '“', '”', '—', '<', '>', '·', '…', '∵');
        $replace_arr = array('&amp;', '&nbsp;', '&quot;', '&#039;', '&ldquo;', '&rdquo;', '&mdash;', '&lt;', '&gt;', '&middot;', '&hellip;', ' ');
        $search_flip = array_flip($search_arr);
        for ($i = 0; $i < $maxi; $i++) {
            $current_str = ord($string[$i]) > 127 ? $string[$i] . $string[++$i] : $string[$i];
            if (in_array($current_str, $search_arr)) {
                $key = $search_flip[$current_str];
                $current_str = str_replace($search_arr[$key], $replace_arr[$key], $current_str);
            }
            $strcut .= $current_str;
        }
    }
    return $strcut . $dot;
}


/**
 * 产生随机字符串
 *
 * @param int $length 输出长度
 * @param string $chars 可选的 ，默认为 0123456789
 * @return   string     字符串
 */
function random($length, $chars = '0123456789')
{
    $hash = '';
    $max = strlen($chars) - 1;
    mt_srand();
    for ($i = 0; $i < $length; $i++) {
        $hash .= $chars[mt_rand(0, $max)];
    }
    return $hash;
}

/**
 * 将字符串转换为数组
 *
 * @param string $data 字符串
 * @return    array    返回数组格式，如果，data为空，则返回空数组
 */
function string2array($data)
{
    $data = trim($data);
    if ($data == '') return array();
    if (strpos($data, 'array') === 0) {
        @eval("\$array = $data;");
    } else {
        if (strpos($data, '{\\') === 0) $data = stripslashes($data);
        $array = json_decode($data, true);
        if (strtolower(CHARSET) == 'gbk') {
            $array = mult_iconv("UTF-8", "GBK//IGNORE", $array);
        }
    }
    return $array;
}

/**
 * 将数组转换为字符串
 *
 * @param array $data 数组
 * @param bool $isformdata 如果为0，则不使用new_stripslashes处理，可选参数，默认为1
 * @return    string    返回字符串，如果，data为空，则返回空
 */
function array2string($data, $isformdata = 1)
{
    if ($data == '' || empty($data)) return '';

    if ($isformdata) $data = new_stripslashes($data);
    if (strtolower(CHARSET) == 'gbk') {
        $data = mult_iconv("GBK", "UTF-8", $data);
    }
    if (version_compare(PHP_VERSION, '5.3.0', '<')) {
        return addslashes(json_encode($data));
    } else {
        return addslashes(json_encode($data, JSON_FORCE_OBJECT));
    }
}

/**
 * 数组转码
 *
 */
function mult_iconv($in_charset, $out_charset, $data)
{
    if (substr($out_charset, -8) == '//IGNORE') {
        $out_charset = substr($out_charset, 0, -8);
    }
    if (is_array($data)) {
        foreach ($data as $key => $value) {
            if (is_array($value)) {
                $key = iconv($in_charset, $out_charset . '//IGNORE', $key);
                $rtn[$key] = mult_iconv($in_charset, $out_charset, $value);
            } elseif (is_string($key) || is_string($value)) {
                if (is_string($key)) {
                    $key = iconv($in_charset, $out_charset . '//IGNORE', $key);
                }
                if (is_string($value)) {
                    $value = iconv($in_charset, $out_charset . '//IGNORE', $value);
                }
                $rtn[$key] = $value;
            } else {
                $rtn[$key] = $value;
            }
        }
    } elseif (is_string($data)) {
        $rtn = iconv($in_charset, $out_charset . '//IGNORE', $data);
    } else {
        $rtn = $data;
    }
    return $rtn;
}

/**
 * 转换字节数为其他单位
 *
 *
 * @param string $filesize 字节大小
 * @return    string    返回大小
 */
function sizecount($filesize)
{
    if ($filesize >= 1073741824) {
        $filesize = round($filesize / 1073741824 * 100) / 100 . ' GB';
    } elseif ($filesize >= 1048576) {
        $filesize = round($filesize / 1048576 * 100) / 100 . ' MB';
    } elseif ($filesize >= 1024) {
        $filesize = round($filesize / 1024 * 100) / 100 . ' KB';
    } else {
        $filesize = $filesize . ' Bytes';
    }
    return $filesize;
}

/**
 * 字符串加密、解密函数
 *
 *
 * @param string $txt 字符串
 * @param string $operation ENCODE为加密，DECODE为解密，可选参数，默认为ENCODE，
 * @param string $key 密钥：数字、字母、下划线
 * @param string $expiry 过期时间
 * @return    string
 */
function sys_auth($string, $operation = 'ENCODE', $key = '', $expiry = 0)
{
    $ckey_length = 4;
    $key = md5($key != '' ? $key : getConfig('sys', 'auth_key'));
    $keya = md5(substr($key, 0, 16));
    $keyb = md5(substr($key, 16, 16));
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length) : substr(md5(microtime()), -$ckey_length)) : '';

    $cryptkey = $keya . md5($keya . $keyc);
    $key_length = strlen($cryptkey);

    $string = $operation == 'DECODE' ? base64_decode(strtr(substr($string, $ckey_length), '-_', '+/')) : sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string;
    $string_length = strlen($string);

    $result = '';
    $box = range(0, 255);

    $rndkey = array();
    for ($i = 0; $i <= 255; $i++) {
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
    }

    for ($j = $i = 0; $i < 256; $i++) {
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
        $tmp = $box[$i];
        $box[$i] = $box[$j];
        $box[$j] = $tmp;
    }

    for ($a = $j = $i = 0; $i < $string_length; $i++) {
        $a = ($a + 1) % 256;
        $j = ($j + $box[$a]) % 256;
        $tmp = $box[$a];
        $box[$a] = $box[$j];
        $box[$j] = $tmp;
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
    }

    if ($operation == 'DECODE') {
        if ((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)) {
            return substr($result, 26);
        } else {
            return '';
        }
    } else {
        return $keyc . rtrim(strtr(base64_encode($result), '+/', '-_'), '=');
    }
}

/**
 * 模板调用
 *
 * @param $module
 * @param $template
 * @param $istag
 * @return unknown_type
 */
function template($module = 'content', $template = 'index', $style = '')
{

    $module = str_replace('/', DIRECTORY_SEPARATOR, $module);
    if (!empty($style) && preg_match('/([a-z0-9\-_]+)/is', $style)) {

    } elseif (empty($style) && !defined('STYLE')) {
        if (defined('SITEID')) {
            $siteid = SITEID;
        } else {
            $siteid = get_cookie('siteid');
        }
        if (!$siteid) $siteid = 1;

        $sitelist = getcache('sitelist', 'commons');

        if (!empty($siteid) && !empty($sitelist[$siteid]['default_style'])) {
            $style = $sitelist[$siteid]['default_style'];
        }
    } elseif (empty($style) && defined('STYLE')) {
        $style = STYLE;
    } else {
        $style = 'default';
    }
    if (!$style) $style = 'default';
    $template_cache = base::load_sys_class('template_cache');//缓存驱动
    //缓存模板文件 wekphp.cc\caches\caches_template\mozhi\admin\content1.php
    $compiledtplfile = ROOT_PATH . 'caches' . DIRECTORY_SEPARATOR . 'caches_template' . DIRECTORY_SEPARATOR . $style . DIRECTORY_SEPARATOR . $module . DIRECTORY_SEPARATOR . $template . '.php';

    //模板文件（非缓存模板）wekphp.cc\templates\mozhi\admin\content1.html
    $tmp_path = ROOT_PATH . 'templates' . DIRECTORY_SEPARATOR . $style . DIRECTORY_SEPARATOR . $module . DIRECTORY_SEPARATOR . $template . '.php';

    //选中风格的模板类型是否存在
    if (file_exists($tmp_path)) {
        //如果缓存模板文件不存在 或者 模板文件的修改时间大于缓存模板文件，就要重新生成缓存模板文件

        if (DEBUG == 0) {// 0：线上: 关闭调试日志 1: 开发模式， 2: 线上调试：日志记录
            //线上才生成缓存，开发者和线上调试不生成缓存
            if (!file_exists($compiledtplfile) || (@filemtime($tmp_path) > @filemtime($compiledtplfile))) {
                dd('生成模板缓存1');
                $template_cache->template_compile($module, $template, $style);
            }
        }
    } else {
        //选中的模板不存在，使用默认缓存模板
        $compiledtplfile = ROOT_PATH . 'caches' . DIRECTORY_SEPARATOR . 'caches_template' . DIRECTORY_SEPARATOR . 'default' . DIRECTORY_SEPARATOR . $module . DIRECTORY_SEPARATOR . $template . '.php';

        //默认模板文件
        $tmp_path = ROOT_PATH . 'templates' . DIRECTORY_SEPARATOR . 'default' . DIRECTORY_SEPARATOR . $module . DIRECTORY_SEPARATOR . $template . '.php';

        //如果默认模板也不存在，提示错误
        if (!file_exists($tmp_path)) {
            //TODO 判断默认缓存模板是否存在，存在就清理 $compiledtplfile
            dd('Template does not exist.' . $tmp_path);
//            showmessage();
        }
        if (DEBUG == 0) {// 0：线上: 关闭调试日志 1: 开发模式， 2: 线上调试：日志记录
            //线上才生成缓存，开发者和线上调试不生成缓存
            //如果默认缓存模板不存在， 或者默认模板更新时间大于默认缓存模板，就重新生成默认模板缓存
            if (!file_exists($compiledtplfile) || (file_exists($tmp_path) && filemtime($tmp_path) > filemtime($compiledtplfile))) {
                dd('生成模板缓存');
                $template_cache->template_compile($module, $template, 'default');
            }
        }
    }
    if (DEBUG == 1) {// 0：线上: 关闭调试日志 1: 开发模式， 2: 线上调试：日志记录
        return $tmp_path;//返回模板路径
    }
    return $compiledtplfile;//返回缓存模板路径
}


/**
 * 输出自定义错误
 *
 * @param $errno 错误号
 * @param $errstr 错误描述
 * @param $errfile 报错文件地址
 * @param $errline 错误行号
 * @return string 错误提示
 */

function my_error_handler($errno, $errstr, $errfile, $errline)
{
    if ($errno == 8) return '';
    $errfile = str_replace(ROOT_PATH, '', $errfile);
    if (getConfig('sys', 'errorlog')) {
        error_log('<?php exit;?>' . date('m-d H:i:s', SYS_TIME) . ' | ' . $errno . ' | ' . str_pad($errstr, 30) . ' | ' . $errfile . ' | ' . $errline . "\r\n", 3, CACHE_PATH . 'error_log.php');
    } else {
        $str = '<div style="font-size:12px;text-align:left; border-bottom:1px solid #9cc9e0; border-right:1px solid #9cc9e0;padding:1px 4px;color:#000000;font-family:Arial, Helvetica,sans-serif;"><span>errorno:' . $errno . ',str:' . $errstr . ',file:<font color="blue">' . $errfile . '</font>,line' . $errline . '<br /><a href="http://faq.phpcms.cn/?type=file&errno=' . $errno . '&errstr=' . urlencode($errstr) . '&errfile=' . urlencode($errfile) . '&errline=' . $errline . '" target="_blank" style="color:red">Need Help?</a></span></div>';
        echo $str;
    }
}

/**
 * 提示信息页面跳转，跳转地址如果传入数组，页面会提示多个地址供用户选择，默认跳转地址为数组的第一个值，时间为5秒。
 * showmessage('登录成功', array('默认跳转地址'=>'http://www.phpcms.cn'));
 * @param string $msg 提示信息
 * @param mixed(string/array) $url_forward 跳转地址
 * @param int $ms 跳转等待时间
 */
function showmessage($msg, $url_forward = 'goback', $ms = 1250, $dialog = '', $returnjs = '')
{
    if ($url_forward === HTTP_REFERER) {
        $url_forward = remove_xss(safe_replace($url_forward));
    }
    if (!defined('IN_ADMIN')) {
        include(admin::admin_tpl('showmessage', 'admin'));
    } else {
        include(template('content', 'message'));
    }
    exit;
}

/**
 * 查询字符是否存在于某字符串
 *
 * @param $haystack 字符串
 * @param $needle 要查找的字符
 * @return bool
 */
function str_exists($haystack, $needle)
{
    return !(strpos($haystack, $needle) === FALSE);
}

/**
 * 取得文件扩展
 *
 * @param $filename 文件名
 * @return 扩展名
 */
function fileext($filename)
{
    return strtolower(trim(substr(strrchr($filename, '.'), 1, 10)));
}

/**
 * 加载模板标签缓存
 * @param string $name 缓存名
 * @param integer $times 缓存时间
 */
function tpl_cache($name, $times = 0)
{
    $filepath = 'tpl_data';
    $info = getcacheinfo($name, $filepath);
    if (SYS_TIME - $info['filemtime'] >= $times) {
        return false;
    } else {
        return getcache($name, $filepath);
    }
}

/**
 * 写入缓存，默认为文件缓存，不加载缓存配置。
 * @param $name 缓存名称
 * @param $data 缓存数据
 * @param $filepath 数据路径（模块名称） caches/cache_$filepath/
 * @param $type 缓存类型[file,memcache,apc]
 * @param $config 配置名称
 * @param $timeout 过期时间
 */
function setcache($name, $data, $filepath = '', $type = 'file', $config = '', $timeout = 0)
{
    if (!preg_match("/^[a-zA-Z0-9_-]+$/", $name)) return false;
    if ($filepath != "" && !preg_match("/^[a-zA-Z0-9_-]+$/", $filepath)) return false;
    base::load_sys_class('cache_factory', '', 0);
    if ($config) {
        $cacheconfig = getConfig('cache');
        $cache = cache_factory::get_instance($cacheconfig)->get_cache($config);
    } else {
        $cache = cache_factory::get_instance()->get_cache($type);
    }

    return $cache->set($name, $data, $timeout, '', $filepath);
}

/**
 * 读取缓存，默认为文件缓存，不加载缓存配置。
 * @param string $name 缓存名称
 * @param $filepath 数据路径（模块名称） caches/cache_$filepath/
 * @param string $config 配置名称
 */
function getcache($name, $filepath = '', $type = 'file', $config = '')
{
    if (!preg_match("/^[a-zA-Z0-9_-]+$/", $name)) return false;
    if ($filepath != "" && !preg_match("/^[a-zA-Z0-9_-]+$/", $filepath)) return false;
    base::load_sys_class('cache_factory', '', 0);
    if ($config) {
        $cacheconfig = getConfig('cache');
        $cache = cache_factory::get_instance($cacheconfig)->get_cache($config);
    } else {
        $cache = cache_factory::get_instance()->get_cache($type);//获取缓驱动
    }
    return $cache->get($name, '', '', $filepath);//获取缓存内容
}

/**
 * 删除缓存，默认为文件缓存，不加载缓存配置。
 * @param $name 缓存名称
 * @param $filepath 数据路径（模块名称） caches/cache_$filepath/
 * @param $type 缓存类型[file,memcache,apc]
 * @param $config 配置名称
 */
function delcache($name, $filepath = '', $type = 'file', $config = '')
{
    if (!preg_match("/^[a-zA-Z0-9_-]+$/", $name)) return false;
    if ($filepath != "" && !preg_match("/^[a-zA-Z0-9_-]+$/", $filepath)) return false;
    base::load_sys_class('cache_factory', '', 0);
    if ($config) {
        $cacheconfig = getConfig('cache');
        $cache = cache_factory::get_instance($cacheconfig)->get_cache($config);
    } else {
        $cache = cache_factory::get_instance()->get_cache($type);
    }
    return $cache->delete($name, '', '', $filepath);
}

/**
 * 读取缓存，默认为文件缓存，不加载缓存配置。
 * @param string $name 缓存名称
 * @param $filepath 数据路径（模块名称） caches/cache_$filepath/
 * @param string $config 配置名称
 */
function getcacheinfo($name, $filepath = '', $type = 'file', $config = '')
{
    if (!preg_match("/^[a-zA-Z0-9_-]+$/", $name)) return false;
    if ($filepath != "" && !preg_match("/^[a-zA-Z0-9_-]+$/", $filepath)) return false;
    base::load_sys_class('cache_factory');
    if ($config) {
        $cacheconfig = getConfig('cache');
        $cache = cache_factory::get_instance($cacheconfig)->get_cache($config);
    } else {
        $cache = cache_factory::get_instance()->get_cache($type);
    }
    return $cache->cacheinfo($name, '', '', $filepath);
}


/**
 * 判断email格式是否正确
 * @param $email
 */
function is_email($email)
{
    return strlen($email) > 6 && preg_match("/^[\w\-\.]+@[\w\-\.]+(\.\w+)+$/", $email);
}

/**
 * iconv 编辑转换
 */
if (!function_exists('iconv')) {
    function iconv($in_charset, $out_charset, $str)
    {
        $in_charset = strtoupper($in_charset);
        $out_charset = strtoupper($out_charset);
        if (function_exists('mb_convert_encoding')) {
            return mb_convert_encoding($str, $out_charset, $in_charset);
        } else {
            base::load_sys_func('iconv');
            $in_charset = strtoupper($in_charset);
            $out_charset = strtoupper($out_charset);
            if ($in_charset == 'UTF-8' && ($out_charset == 'GBK' || $out_charset == 'GB2312')) {
                return utf8_to_gbk($str);
            }
            if (($in_charset == 'GBK' || $in_charset == 'GB2312') && $out_charset == 'UTF-8') {
                return gbk_to_utf8($str);
            }
            return $str;
        }
    }
}


/**
 * 获取当前的站点ID
 */
function get_siteid()
{
    static $siteid;
    if (!empty($siteid)) return $siteid;
    if (defined('IN_ADMIN')) {
        if ($d = param::get_cookie('siteid')) {
            $siteid = $d;
        } else {
            return '';
        }
    } else {
        $data = getcache('sitelist', 'commons');
        if (!is_array($data)) return '1';
        $site_url = SITE_PROTOCOL . SITE_URL;
        foreach ($data as $v) {
            if ($v['url'] == $site_url . '/') $siteid = $v['siteid'];
        }
    }
    if (empty($siteid)) $siteid = 1;
    return $siteid;
}


/**
 * IE浏览器判断
 */

function is_ie()
{
    $useragent = strtolower($_SERVER['HTTP_USER_AGENT']);
    if ((strpos($useragent, 'opera') !== false) || (strpos($useragent, 'konqueror') !== false)) return false;
    if (strpos($useragent, 'msie ') !== false) return true;
    return false;
}


/**
 * 文件下载
 * @param $filepath 文件路径
 * @param $filename 文件名称
 */

function file_down($filepath, $filename = '')
{
    if (!$filename) $filename = basename($filepath);
    if (is_ie()) $filename = rawurlencode($filename);
    $filetype = fileext($filename);
    $filesize = sprintf("%u", filesize($filepath));
    if (ob_get_length() !== false) @ob_end_clean();
    header('Pragma: public');
    header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
    header('Cache-Control: no-store, no-cache, must-revalidate');
    header('Cache-Control: pre-check=0, post-check=0, max-age=0');
    header('Content-Transfer-Encoding: binary');
    header('Content-Encoding: none');
    header('Content-type: ' . $filetype);
    header('Content-Disposition: attachment; filename="' . $filename . '"');
    header('Content-length: ' . $filesize);
    readfile($filepath);
    exit;
}

/**
 * 判断字符串是否为utf8编码，英文和半角字符返回ture
 * @param $string
 * @return bool
 */
function is_utf8($string)
{
    return preg_match('%^(?:
					[\x09\x0A\x0D\x20-\x7E] # ASCII
					| [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
					| \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
					| [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
					| \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
					| \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
					| [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
					| \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
					)*$%xs', $string);
}


/**
 * 检查密码长度是否符合规定
 *
 * @param STRING $password
 * @return    TRUE or FALSE
 */
function is_password($password)
{
    $strlen = strlen($password);
    if ($strlen >= 6 && $strlen <= 20) return true;
    return false;
}

/**
 * 检测输入中是否含有错误字符
 *
 * @param char $string 要检查的字符串名称
 * @return TRUE or FALSE
 */
function is_badword($string)
{
    $badwords = array("\\", '&', ' ', "'", '"', '/', '*', ',', '<', '>', "\r", "\t", "\n", "#");
    foreach ($badwords as $value) {
        if (strpos($string, $value) !== FALSE) {
            return TRUE;
        }
    }
    return FALSE;
}

/**
 * 检查用户名是否符合规定
 *
 * @param STRING $username 要检查的用户名
 * @return    TRUE or FALSE
 */
function is_username($username)
{
    $strlen = strlen($username);
    if (is_badword($username) || !preg_match("/^[a-zA-Z0-9_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]+$/", $username)) {
        return false;
    } elseif (20 < $strlen || $strlen < 2) {
        return false;
    }
    return true;
}

/**
 * 检查id是否存在于数组中
 *
 * @param $id
 * @param $ids
 * @param $s
 */
function check_in($id, $ids = '', $s = ',')
{
    if (!$ids) return false;
    $ids = explode($s, $ids);
    return is_array($id) ? array_intersect($id, $ids) : in_array($id, $ids);
}

/**
 * 对数据进行编码转换
 * @param array/string $data       数组
 * @param string $input 需要转换的编码
 * @param string $output 转换后的编码
 */
function array_iconv($data, $input = 'gbk', $output = 'utf-8')
{
    if (!is_array($data)) {
        return iconv($input, $output, $data);
    } else {
        foreach ($data as $key => $val) {
            if (is_array($val)) {
                $data[$key] = array_iconv($val, $input, $output);
            } else {
                $data[$key] = iconv($input, $output, $val);
            }
        }
        return $data;
    }
}

/**
 * 生成缩略图函数
 * @param  $imgurl 图片路径
 * @param  $width  缩略图宽度
 * @param  $height 缩略图高度
 * @param  $autocut 是否自动裁剪 默认裁剪，当高度或宽度有一个数值为0是，自动关闭
 * @param  $smallpic 无图片是默认图片路径
 */
function thumb($imgurl, $width = 100, $height = 100, $autocut = 1, $smallpic = 'nopic.gif')
{
    global $image;
    $upload_url = getConfig('sys', 'upload_url');
    $upload_path = getConfig('sys', 'upload_path');
    if (empty($imgurl)) return IMG_PATH . $smallpic;
    $imgurl_replace = str_replace($upload_url, '', $imgurl);
    if (!extension_loaded('gd') || strpos($imgurl_replace, '://')) return $imgurl;
    if (!file_exists($upload_path . $imgurl_replace)) return IMG_PATH . $smallpic;

    list($width_t, $height_t, $type, $attr) = getimagesize($upload_path . $imgurl_replace);
    if ($width >= $width_t || $height >= $height_t) return $imgurl;

    $newimgurl = dirname($imgurl_replace) . '/thumb_' . $width . '_' . $height . '_' . basename($imgurl_replace);

    if (file_exists($upload_path . $newimgurl)) return $upload_url . $newimgurl;

    if (!is_object($image)) {
        base::load_sys_class('image', '', '0');
        $image = new image(1, 0);
    }
    return $image->thumb($upload_path . $imgurl_replace, $upload_path . $newimgurl, $width, $height, '', $autocut) ? $upload_url . $newimgurl : $imgurl;
}

/**
 * 水印添加
 * @param $source 原图片路径
 * @param $target 生成水印图片途径，默认为空，覆盖原图
 * @param $siteid 站点id，系统需根据站点id获取水印信息
 */
function watermark($source, $target = '', $siteid = '')
{
    global $image_w;
    if (empty($source)) return $source;
    if (!extension_loaded('gd') || strpos($source, '://')) return $source;
    if (!$target) $target = $source;
    if (!is_object($image_w)) {
        base::load_sys_class('image', '', '0');
        $image_w = new image(0, $siteid);
    }
    $image_w->watermark($source, $target);
    return $target;
}


/**
 * 将附件地址转换为绝对地址
 * @param $path 附件地址
 */
function atturl($path)
{
    if (strpos($path, ':/')) {
        return $path;
    } else {
        $sitelist = getcache('sitelist', 'commons');
        $siteid = get_siteid();
        $siteurl = $sitelist[$siteid]['domain'];
        $domainlen = strlen($sitelist[$siteid]['domain']) - 1;
        $path = $siteurl . $path;
        $path = substr_replace($path, '/', strpos($path, '//', $domainlen), 2);
        return $path;
    }
}


/**
 * 生成上传附件验证
 * @param $args   参数
 * @param $operation   操作类型(加密解密)
 */

function upload_key($args)
{
    $pc_auth_key = md5(WEKCMS_PATH . 'upload' . getConfig('sys', 'auth_key') . $_SERVER['HTTP_USER_AGENT']);
    $authkey = md5($args . $pc_auth_key);
    return $authkey;
}

/**
 * 生成验证key
 * @param $prefix   参数
 * @param $suffix   参数
 */
function get_auth_key($prefix, $suffix = "")
{
    if ($prefix == 'login') {
        $pc_auth_key = md5(WEKCMS_PATH . 'login' . getConfig('sys', 'auth_key') . ip());
    } else if ($prefix == 'email') {
        $pc_auth_key = md5(WEKCMS_PATH . 'email' . getConfig('sys', 'auth_key'));
    } else {
        $pc_auth_key = md5(WEKCMS_PATH . 'other' . getConfig('sys', 'auth_key') . $suffix);
    }
    $authkey = md5($prefix . $pc_auth_key);
    return $authkey;
}

/**
 * 文本转换为图片
 * @param string $txt 图形化文本内容
 * @param int $fonttype 无外部字体时生成文字大小，取值范围1-5
 * @param int $fontsize 引入外部字体时，字体大小
 * @param string $font 字体名称 字体请放于phpcms\libs\data\font下
 * @param string $fontcolor 字体颜色 十六进制形式 如FFFFFF,FF0000
 */
function string2img($txt, $fonttype = 5, $fontsize = 16, $font = '', $fontcolor = 'FF0000', $transparent = '1')
{
    if (empty($txt)) return false;
    if (function_exists("imagepng")) {
        $txt = urlencode(sys_auth($txt));
        $txt = '<img src="' . APP_PATH . 'api.php?op=creatimg&txt=' . $txt . '&fonttype=' . $fonttype . '&fontsize=' . $fontsize . '&font=' . $font . '&fontcolor=' . $fontcolor . '&transparent=' . $transparent . '" align="absmiddle">';
    }
    return $txt;
}


function getmicrotime()
{
    list($usec, $sec) = explode(" ", microtime());
    return ((float)$usec + (float)$sec);
}

/**
 * 读取缓存动态页面
 */
function cache_page_start()
{
    $relate_url = isset($_SERVER['REQUEST_URI']) ? safe_replace($_SERVER['REQUEST_URI']) : $php_self . (isset($_SERVER['QUERY_STRING']) ? '?' . safe_replace($_SERVER['QUERY_STRING']) : $path_info);
    define('CACHE_PAGE_ID', md5($relate_url));
    $contents = getcache(CACHE_PAGE_ID, 'page_tmp/' . substr(CACHE_PAGE_ID, 0, 2));
    if ($contents && intval(substr($contents, 15, 10)) > SYS_TIME) {
        echo substr($contents, 29);
        exit;
    }
    if (!defined('HTML')) define('HTML', true);
    return true;
}

/**
 * 写入缓存动态页面
 */
function cache_page($ttl = 360, $isjs = 0)
{
    if ($ttl == 0 || !defined('CACHE_PAGE_ID')) return false;
    $contents = ob_get_contents();

    if ($isjs) $contents = format_js($contents);
    $contents = "<!--expiretime:" . (SYS_TIME + $ttl) . "-->\n" . $contents;
    setcache(CACHE_PAGE_ID, $contents, 'page_tmp/' . substr(CACHE_PAGE_ID, 0, 2));
}

/**
 *
 * 获取远程内容
 * @param $url 接口url地址
 * @param $timeout 超时时间
 */
function pc_file_get_contents($url, $timeout = 30)
{
    $stream = stream_context_create(array('http' => array('timeout' => $timeout)));
    return @file_get_contents($url, 0, $stream);
}

?>